﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ScriptEngine.Script.Extension
{
	/// <summary>
	/// 代码提示注入类型
	/// p1: 对象和常量需要以属性的形式存入类中
	/// </summary>
	public enum ExtensionType
	{
		Func,   // 方法
		Object, // 对象
		Const,  // 常量
		NotFunc, // 未知但知道不是方法
		Property // 属性值: 可被赋值的
	}

	/// <summary>
	/// 标注该数据不可用于代码提示
	/// </summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Enum | AttributeTargets.Method)]
	public class CodeNotTip : Attribute { }

	/// <summary>
	/// 使用该特征，方法可以不带父对象的显示在脚本编辑器中如a.b()则可以直接提示b()
	/// </summary>
	[AttributeUsage(AttributeTargets.Class)]
	public class ExtMethodShowDitchObj : Attribute
	{
		/// <summary>
		/// 显示时是否包含父元素
		/// </summary>
		public bool IncludeParent { get; protected set; }

		/// <summary>
		/// 父对象描述
		/// </summary>
		public string ParentDesc { get; protected set; }

		public ExtMethodShowDitchObj() : this(true, null) { }

		public ExtMethodShowDitchObj(bool includeParent, string parentDesc)
		{
			IncludeParent = includeParent;
			ParentDesc = parentDesc;
		}
	}

	/// <summary>
	/// 使用该特征，属性可以不带父对象的显示在脚本编辑器中如a.b则可以直接提示b
	/// 用法类似ExtMethodShowDitchObj
	/// </summary>
	[AttributeUsage(AttributeTargets.Class)]
	public class ExtPropShowDitchObj : Attribute
	{
		/// <summary>
		/// 显示时是否包含父元素
		/// </summary>
		public bool IncludeParent { get; protected set; }

		/// <summary>
		/// 父对象描述
		/// </summary>
		public string ParentDesc { get; protected set; }
		public ExtPropShowDitchObj() : this(true, null) { }

		public ExtPropShowDitchObj(bool includeParent, string parentDesc)
		{
			IncludeParent = includeParent;
			ParentDesc = parentDesc;
		}
	}

	/// <summary>
	/// 属性用于标注方法,对象，属性注入到脚本中的类型
	/// </summary>
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
	public class ScriptCallCsharp : Attribute
	{
		/// <summary>
		/// 注入类型
		/// </summary>
		public ExtensionType Type { get; }

		/// <summary>
		/// 注入到脚本环境后的注入名称
		/// </summary>
		public string Name { get; }

		/// <summary>
		/// 用法说明
		/// </summary>
		public string Statement { get; }

		/// <summary>
		/// 用于注入的方法的委托类型(只注入Lua环境可不传)
		/// </summary>
		public Type DelegateType { get; }

		public ScriptCallCsharp(ExtensionType type, Type delegateType = null, string name = "", string statement = "")
		{
			Type = type;
			Name = name;
			Statement = statement;
			DelegateType = delegateType;
		}

		public ScriptCallCsharp(ExtensionType type, string name, string statement) : this(type, null, name, statement) { }

		public ScriptCallCsharp(ExtensionType type, Type delegateType, string name) : this(type, delegateType, name, "") { }

		public ScriptCallCsharp(ExtensionType type, string name) : this(type, null, name, "") { }

		public ScriptCallCsharp(ExtensionType type) : this(type, null, "", "") { }

		/// <summary>
		/// 获取该属性所处元素的类型
		/// </summary>
		/// <returns>类型名</returns>
		public string GetTypeName()
		{
			return GetTypeName(Type);
		}

		/// <summary>
		/// 获取该属性所处元素的类型
		/// </summary>
		/// <param name="type">类型名</param>
		/// <returns>类型名</returns>
		public static string GetTypeName(ExtensionType type)
		{
			switch (type)
			{
				case ExtensionType.Func:
					return "function";
				case ExtensionType.Const:
					return "const value";
				case ExtensionType.NotFunc:
					return "object or const val";
				default:
					return type.ToString().ToLower();
			}
		}

	}
}
